import { _decorator, Component, Node, RigidBody2D, Vec3, Vec2, math, Camera, Quat, misc, UITransform } from 'cc';
import { TouchInput } from './TouchInput';
const { ccclass, property } = _decorator;

@ccclass('CarControl')
export class CarControl extends Component {

    @property({type: RigidBody2D})
    carRigidBody: RigidBody2D

    touchInput: TouchInput
    
    @property({type: Camera})
    gameCamera: Camera

    //汽车当前作用在速度上的力
    speedForce = 0;

    //汽车最大可作用在速度上的力
    maxSpeedForce = 70;
    
    //汽车作用在速度上的力的自增/递减值
    aSpeedForce = 20;

    fixLinearDamping = 0.9

    start() {
        console.log('------------start-----------------')
        this.touchInput = TouchInput.Instance()
    }

    isLeft(){
        if(this.isBack()){
            return this.touchInput.getHorizontal(this.node,this.gameCamera)>0;
        }
        return this.touchInput.getHorizontal(this.node,this.gameCamera)<0;
    }

    isRight(){
        if(this.isBack()){
            return this.touchInput.getHorizontal(this.node,this.gameCamera)<0;
        }
        return this.touchInput.getHorizontal(this.node,this.gameCamera)>0;
    }

    isRun(){
        return this.touchInput.getVertical(this.node,this.gameCamera)>0
    }

    isBack(){
        return this.touchInput.getVertical(this.node,this.gameCamera)<0
    }

    update(deltaTime: number) {
       
        var inTouching: boolean = this.touchInput.inTouch
        if(!inTouching){
            return
        }

        var inRun = this.isRun()
        var inBack = this.isBack()
        var rigidBody: RigidBody2D = this.node.getComponent(RigidBody2D)

        //inRun表示是否向前加速 inBack表示是否向后加速 当inRun和inBack都是false时表示汽车靠惯性在行驶
        if(inRun){ 
            rigidBody.linearDamping = this.fixLinearDamping * (Math.abs(this.speedForce)/this.maxSpeedForce)
            if(this.speedForce < this.maxSpeedForce){
                this.speedForce += this.aSpeedForce * deltaTime
            }else{
                this.speedForce = this.maxSpeedForce
            }
        }else if(inBack){
            rigidBody.linearDamping = this.fixLinearDamping * (Math.abs(this.speedForce)/this.maxSpeedForce)
            this.speedForce -= this.aSpeedForce * deltaTime
            if(this.speedForce < -this.maxSpeedForce * 0.5){
                this.speedForce = -this.maxSpeedForce * 0.5
            }
        }else{
            rigidBody.linearDamping = this.fixLinearDamping
            this.speedForce-=50 * deltaTime
            if(this.speedForce<0){
                this.speedForce = 0;
            }  
        }


        var inLeft: boolean = this.isLeft();
        var inRight: boolean = this.isRight();
        var uiWidth: number = this.node.getComponent(UITransform).width
        var uiHeight: number = this.node.getComponent(UITransform).height

        var stableCenterPos: Vec3 = this.node.getPosition();
            
        if(inLeft){
            stableCenterPos.add(new Vec3(- uiWidth/2,uiHeight/2));
        }else if(inRight){
            stableCenterPos.add(new Vec3(uiWidth/2,uiHeight/2));
        }
        if(inLeft || inRight){
            stableCenterPos = this.rotateByPoint(stableCenterPos, 
                new Vec3(this.node.getPosition()),
                this.node.angle,new Vec3(0,0,1)); 
        }

        var turnForce = 300
        if(inLeft){
            var resPos: Vec3 = this.rotateByPoint(this.node.getPosition(),stableCenterPos,deltaTime*(turnForce/3),new Vec3(0,0,1))
            this.node.setPosition(resPos)
            this.node.angle +=deltaTime * turnForce;
        }else if(inRight){
            var resPos = this.rotateByPoint(this.node.getPosition(),stableCenterPos,-deltaTime*(turnForce/3),new Vec3(0,0,1))
            this.node.setPosition(resPos)
            this.node.angle -=deltaTime * turnForce;
        }

        var force = Math.abs(this.speedForce)
        let rad = -misc.degreesToRadians(this.node.angle)
        var forcePos: Vec2 = new Vec2(force * Math.sin(rad),force * Math.cos(rad))
        if(this.isBack()){
            forcePos.x = -forcePos.x
            forcePos.y = - forcePos.y
        }

        rigidBody.applyForceToCenter(forcePos,false);
    }

    cacheCalcQuat = new Quat()

    cacheCalcDir = new Vec3()

    /**
     * A点绕B点以x或y或z方向旋转一定角度后A点的新坐标
     * @param target A点坐标
     * @param center B点坐标
     * @param angle 旋转的角度
     * @param axis x轴还是y轴还是z轴，本游戏中只会有z轴的情况
     * @returns 旋转后A点的坐标
     */
    rotateByPoint(target: Vec3, center: Vec3, angle: number, axis: Vec3 = Vec3.UP) : Vec3 {
        //let dir = new Vec3()
        let rotated = new Vec3()

        Vec3.subtract(this.cacheCalcDir,target,center);

        let rad = misc.degreesToRadians(angle)

        Quat.fromAxisAngle(this.cacheCalcQuat,axis,rad)
        Vec3.transformQuat(rotated,this.cacheCalcDir,this.cacheCalcQuat)
        Vec3.add(rotated,center,rotated);

        return rotated;
    }
}

